package net.cyndeline.GUI

import java.util.UUID
import javafx.scene.Node
import net.cyndeline.entitySystem.EntityRef
import javafx.scene.layout.Pane

/**
 * This is the only interface available for the programs logic
 * to communicate changes to the GUI map state, by adding, moving and
 * removing objects on the map view.
 * 
 * The modifier does not have access to the actual entity objects,
 * only their graphical representations. Communicating changes is done by
 * sending a fresh copy of the state at the tiles being changed.
 * 
 * Out of the four presentation layers, only agents move around on the map.
 */
trait MapModifier {
  
  /**
   * Retrieves the top-most node of the map that is being modified.
   */
  def map: Pane
  
  /**
   * Clears previous map data if any. Map retains the same size.
   */
  def clear()
  
  /**
   * Creates a new map of the specified size. Clears the previous map data if 
   * any exists.
   * 
   * @param width Width of the map in pixels.
   * @param height Height of the map in pixels.
   * @param tileXAmount Number of tiles along the x axis.
   * @param tileYAmount Number of tiles along the y axis.
   */
  def create(width: Int, height: Int, tileXAmount: Int, tileYAmount: Int)
  
  /**
   * Specifies the tile size. Graphics drawn on the background layer
   * will conform to this size, even if it means adjusting the images ratio.
   */
  //def setTileSize(width: Int, height: Int)
  
  /**
   * Adds a list of entities to the map by converting them internally.
   * Only entities containing the necessary rendering data will be
   * added this way.
   */
  def addObjects(x: Int, y: Int, entities: List[EntityRef])
  
  /**
   * Moves an object by converting it internally.
   */
  def moveObject(mover: EntityRef, start: (Int, Int), stop: (Int, Int), newTile: List[EntityRef], oldTile: List[EntityRef])
  
  /**
   * Adds a graphical effect to a position to make it appear as under
   * fog of war.
   */
  def addFogOfWar(x: Int, y: Int)
  
  /**
   * Removes the fog-of-war effect present on a map location, if any.
   */
  def removeFogOfWar(x: Int, y: Int)
  
  /**
   * Highlight a single tile on the map to show where the mouse pointer
   * is targeting.
   */
  def mouseHighlightOn(x: Int, y: Int)
  
  /**
   * Disables mouse highlight.
   */
  def mouseHighlightOff(x: Int, y: Int)
  
  /**
   * Highlight a single tile to mark it as a position the player will walk over
   * when moving from his/her current position to where the mouse pointer
   * is targeting.
   */
  def walkPathHighlightOn(x: Int, y: Int)
  
  /**
   * Disables walk path highlight.
   */
  def walkPathHighlightOff(x: Int, y: Int)
  
  /**
   * Processes the entire map and paints it on the map if the underlying
   * implementation makes use of it.
   */
  def paint()
}

/**
 * Represents different layers on the map. The only layer that isn't locked
 * into a grid is the Agent. Any object that should animate movement should
 * be placed there.
 */
sealed trait MapLayer

/*
 * Provides color underneath tile ascii, not visible in graphics mode.
 */
case object Cover extends MapLayer

/*
 * The lowest layer such as walls and floors.
 */
case object Background extends MapLayer

/*
 * Things that should be displayed on top of the background, such as
 * water and grass.
 */
case object Decoration extends MapLayer

/*
 * Items on the ground, such as loot and corpses. More important than
 * decoration, and should be given precedence if the choice is to be
 * made between background, decoration and item.
 */
case object Item extends MapLayer

/*
 * Moving, interacting objects that always should be displayed
 * on top of everything else if a choice has to be made.
 */
case object Agent extends MapLayer